package com.imut.lagain.service.impl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.imut.lagain.config.FileUploadConfig;
import com.imut.lagain.service.IFileUploadService;
import com.imut.lagain.util.FileUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.CompletableFuture;

/**
 * 文件上传服务实现类
 */
@Service
@RequiredArgsConstructor
public class FileUploadServiceImpl implements IFileUploadService {
    private static final Logger log = LoggerFactory.getLogger(FileUploadServiceImpl.class);

    
    private final FileUploadConfig fileUploadConfig;
    private final FileUtil fileUtil;
    private static final Map<String, String> CONTENT_TYPE_MAP = new HashMap<>();
    static {
        CONTENT_TYPE_MAP.put("image/jpeg", "images");
        CONTENT_TYPE_MAP.put("image/jpg", "images");
        CONTENT_TYPE_MAP.put("image/png", "images");
        CONTENT_TYPE_MAP.put("image/gif", "images");
        CONTENT_TYPE_MAP.put("image/webp", "images");
        CONTENT_TYPE_MAP.put("image/bmp", "images");
        CONTENT_TYPE_MAP.put("audio/mpeg", "audio");
        CONTENT_TYPE_MAP.put("audio/mp3", "audio");
        CONTENT_TYPE_MAP.put("audio/wav", "audio");
        CONTENT_TYPE_MAP.put("audio/ogg", "audio");
        CONTENT_TYPE_MAP.put("audio/aac", "audio");
        CONTENT_TYPE_MAP.put("audio/m4a", "audio");
        CONTENT_TYPE_MAP.put("audio/amr", "audio");
        CONTENT_TYPE_MAP.put("video/mp4", "video");
        CONTENT_TYPE_MAP.put("video/avi", "video");
        CONTENT_TYPE_MAP.put("video/mov", "video");
        CONTENT_TYPE_MAP.put("video/wmv", "video");
        CONTENT_TYPE_MAP.put("video/flv", "video");
        CONTENT_TYPE_MAP.put("video/webm", "video");
    }
    private static final Map<String, Long> SIZE_LIMITS = new HashMap<>();
    static {
        SIZE_LIMITS.put("images", 10L * 1024 * 1024); // 10MB
        SIZE_LIMITS.put("audio", 50L * 1024 * 1024);  // 50MB
        SIZE_LIMITS.put("video", 200L * 1024 * 1024); // 200MB
    }
    
    @Override
    public Map<String, Object> uploadSingleFile(MultipartFile file, Long userId, String category) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            String validationError = validateFile(file, category);
            if (validationError != null) {
                result.put("success", false);
                result.put("error", validationError);
                return result;
            }
            String relativePath = generateFilePath(file, userId, category);
            String absolutePath = Paths.get(fileUploadConfig.getUploadPath(), relativePath).toString();
            createDirectories(Paths.get(absolutePath).getParent());
            file.transferTo(new File(absolutePath));
            result.put("success", true);
            result.put("fileName", file.getOriginalFilename());
            result.put("filePath", relativePath);
            result.put("fileSize", file.getSize());
            result.put("fileType", getFileType(file));
            result.put("contentType", file.getContentType());
            result.put("uploadTime", LocalDateTime.now());
            result.put("url", "/api/files/" + relativePath.replace("\\", "/"));
            
            log.info("文件上传成功: userId={}, fileName={}, size={}", 
                    userId, file.getOriginalFilename(), file.getSize());
            
        } catch (Exception e) {
            log.error("文件上传失败: userId={}, fileName={}", userId, file.getOriginalFilename(), e);
            result.put("success", false);
            result.put("error", "文件上传失败: " + e.getMessage());
        }
        
        return result;
    }
    
    @Override
    public CompletableFuture<List<Map<String, Object>>> uploadMultipleFiles(
            List<MultipartFile> files, Long userId, String category) {
        return CompletableFuture.supplyAsync(() -> {
            List<Map<String, Object>> results = new ArrayList<>();
            
            for (MultipartFile file : files) {
                try {
                    Map<String, Object> result = uploadSingleFile(file, userId, category);
                    results.add(result);
                    Thread.sleep(50);
                    
                } catch (Exception e) {
                    log.error("批量上传文件失败: fileName={}", file.getOriginalFilename(), e);
                    Map<String, Object> errorResult = new HashMap<>();
                    errorResult.put("success", false);
                    errorResult.put("fileName", file.getOriginalFilename());
                    errorResult.put("error", e.getMessage());
                    results.add(errorResult);
                }
            }
            
            log.info("批量文件上传完成: userId={}, 总数={}, 成功={}", 
                    userId, files.size(), 
                    results.stream().mapToInt(r -> (Boolean) r.get("success") ? 1 : 0).sum());
            
            return results;
        });
    }
    
    @Override
    public Map<String, Object> uploadImage(MultipartFile file, Long userId) {
        return uploadSingleFile(file, userId, "images");
    }
    
    @Override
    public Map<String, Object> uploadAudio(MultipartFile file, Long userId) {
        return uploadSingleFile(file, userId, "audio");
    }
    
    @Override
    public Map<String, Object> uploadVideo(MultipartFile file, Long userId) {
        return uploadSingleFile(file, userId, "video");
    }
    
    @Override
    public boolean deleteFile(String filePath) {
        try {
            String absolutePath = Paths.get(fileUploadConfig.getUploadPath(), filePath).toString();
            File file = new File(absolutePath);
            
            if (file.exists()) {
                boolean deleted = file.delete();
                if (deleted) {
                } else {
                    log.warn("文件删除失败: {}", filePath);
                }
                return deleted;
            } else {
                log.warn("要删除的文件不存在: {}", filePath);
                return false;
            }
            
        } catch (Exception e) {
            log.error("删除文件时发生异常: {}", filePath, e);
            return false;
        }
    }
    
    @Override
    public boolean fileExists(String filePath) {
        try {
            String absolutePath = Paths.get(fileUploadConfig.getUploadPath(), filePath).toString();
            return new File(absolutePath).exists();
        } catch (Exception e) {
            log.error("检查文件存在性时发生异常: {}", filePath, e);
            return false;
        }
    }
    
    @Override
    public Map<String, Object> getFileInfo(String filePath) {
        Map<String, Object> info = new HashMap<>();
        
        try {
            String absolutePath = Paths.get(fileUploadConfig.getUploadPath(), filePath).toString();
            File file = new File(absolutePath);
            
            if (file.exists()) {
                info.put("exists", true);
                info.put("fileName", file.getName());
                info.put("fileSize", file.length());
                info.put("lastModified", new Date(file.lastModified()));
                info.put("isDirectory", file.isDirectory());
                info.put("canRead", file.canRead());
                info.put("canWrite", file.canWrite());
            } else {
                info.put("exists", false);
            }
            
        } catch (Exception e) {
            log.error("获取文件信息时发生异常: {}", filePath, e);
            info.put("exists", false);
            info.put("error", e.getMessage());
        }
        
        return info;
    }
    
    /**
     * 验证文件
     */
    private String validateFile(MultipartFile file, String category) {
        if (file == null || file.isEmpty()) {
            return "文件不能为空";
        }
        
        String originalFilename = file.getOriginalFilename();
        if (originalFilename == null || originalFilename.trim().isEmpty()) {
            return "文件名不能为空";
        }
        
        String contentType = file.getContentType();
        if (contentType == null) {
            return "无法识别文件类型";
        }
        String detectedCategory = CONTENT_TYPE_MAP.get(contentType.toLowerCase());
        if (detectedCategory == null) {
            return "不支持的文件类型: " + contentType;
        }
        
        if (category != null && !category.equals(detectedCategory)) {
            return "文件类型不匹配，期望: " + category + "，实际: " + detectedCategory;
        }
        Long sizeLimit = SIZE_LIMITS.get(detectedCategory);
        if (sizeLimit != null && file.getSize() > sizeLimit) {
            return String.format("文件大小超出限制，最大允许: %.1fMB", sizeLimit / 1024.0 / 1024.0);
        }
        String extension = getFileExtension(originalFilename).toLowerCase();
        if (!isValidExtension(extension, detectedCategory)) {
            return "不支持的文件扩展名: " + extension;
        }
        
        return null; // 验证通过
    }
    
    /**
     * 生成文件路径
     */
    private String generateFilePath(MultipartFile file, Long userId, String category) {
        String originalFilename = file.getOriginalFilename();
        String extension = getFileExtension(originalFilename);
        String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
        String randomStr = UUID.randomUUID().toString().replace("-", "").substring(0, 8);
        String newFilename = timestamp + "_" + randomStr + extension;
        String dateDir = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy/MM/dd"));
        
        if (category == null) {
            category = CONTENT_TYPE_MAP.get(file.getContentType());
        }
        
        return category + File.separator + userId + File.separator + dateDir + File.separator + newFilename;
    }
    
    /**
     * 创建目录
     */
    private void createDirectories(Path dirPath) throws IOException {
        if (!Files.exists(dirPath)) {
            Files.createDirectories(dirPath);
        }
    }
    
    /**
     * 获取文件类型
     */
    private String getFileType(MultipartFile file) {
        String contentType = file.getContentType();
        if (contentType == null) {
            return "unknown";
        }
        
        if (contentType.startsWith("image/")) {
            return "image";
        } else if (contentType.startsWith("audio/")) {
            return "audio";
        } else if (contentType.startsWith("video/")) {
            return "video";
        } else {
            return "other";
        }
    }
    
    /**
     * 获取文件扩展名
     */
    private String getFileExtension(String filename) {
        if (filename == null || filename.isEmpty()) {
            return "";
        }
        
        int lastDotIndex = filename.lastIndexOf('.');
        if (lastDotIndex == -1 || lastDotIndex == filename.length() - 1) {
            return "";
        }
        
        return filename.substring(lastDotIndex);
    }
    
    /**
     * 验证文件扩展名是否有效
     */
    private boolean isValidExtension(String extension, String category) {
        switch (category) {
            case "images":
                return Arrays.asList(".jpg", ".jpeg", ".png", ".gif", ".webp", ".bmp").contains(extension);
            case "audio":
                return Arrays.asList(".mp3", ".wav", ".m4a", ".aac", ".amr", ".ogg").contains(extension);
            case "video":
                return Arrays.asList(".mp4", ".avi", ".mov", ".wmv", ".flv", ".webm").contains(extension);
            default:
                return false;
        }
    }
}

